package com.cs.framework.web.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.cs.framework.web.context.WebApplication;
import com.cs.framework.web.exception.WebExceptionHelper;
import com.cs.framework.web.handler.Handler;
import com.cs.framework.web.util.WebConstant;
import com.cs.framework.web.view.View;
import com.cs.framework.web.view.ViewInfo;

/**
 * 主分配器
 * 
 * @author hedongzhou
 * 
 */
public class DispatcherServlet extends HttpServlet {

	private static final long serialVersionUID = -417476371050194922L;

	private final Log logger = LogFactory.getLog(getClass());

	/**
	 * 应用上下文
	 */
	private WebApplication application;

	/**
	 * 处理器
	 */
	private List<Handler> handlerList;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doDispatch(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
			IOException {
		doDispatch(request, response);
	}

	/**
	 * 分配请求
	 * 
	 * @param request
	 * @param response
	 */
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
		ViewInfo viewInfo = null;

		// 寻找合适的处理器来处理请求
		for (Handler handler : handlerList) {
			// 判断是否可以处理
			if (handler.canHandler(request)) {
				// 处理请求
				viewInfo = handler.handler(request, response);
				break;
			}
		}

		if (viewInfo != null) {
			render(request, response, viewInfo);
		}
	}

	/**
	 * 渲染视图
	 * 
	 * @param request
	 * @param response
	 * @param viewInfo
	 * @param pathInfo
	 */
	protected void render(HttpServletRequest request, HttpServletResponse response, ViewInfo viewInfo) {
		// 得到视图
		View view = application.getView(viewInfo.getViewName());

		if (view != null) {
			// 进行渲染
			ViewInfo newViewInfo = view.render(request, response, viewInfo);

			// 判断是否需要更新视图进行重复渲染
			if (newViewInfo != null) {
				render(request, response, newViewInfo);
			}
		}
	}

	/**
	 * 初始化Servlet
	 * 
	 * @param config
	 */
	public void init(ServletConfig config) throws ServletException {
		logger.info("CS DispatcherServlet init...");

		super.init(config);

		ServletContext context = config.getServletContext();

		// 从Servlet上下文中获取应用上下文
		application = (WebApplication) context.getAttribute(WebConstant.APPLICATION_CONTEXT_ATTR);

		if (application == null) {
			WebExceptionHelper.throwWebException("W011");
		}

		// 获得处理器
		handlerList = application.getHandlerList();

		logger.info("CS DispatcherServlet finish...");
	}

}
